package com.zh.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.zh.filter.AuthFilter;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @Description:
 * @ClassName ShiroConfig
 * @date: 2021.04.09 16:35
 * @Author: zhanghang
 */

@Configuration
public class ShiroConfig {
    //ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("DefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        /*
        anon:无需认证可以访问
        authc：必须认证才能访问
        user：必须拥有 记住我 功能才能用
        perms：拥有对某个资源的权限才能访问
        role:拥有某个角色权限才能访问
         */
        //登录拦截
        Map<String, String> filterMap = new LinkedHashMap<>();
        //用户进入登录界面，无需认证
        filterMap.put("/", "anon");
        filterMap.put("/login", "anon");
        filterMap.put("/tologin", "anon");
        //用户进入系统，必须进行登录验证
        filterMap.put("/sys/*", "authc");
        //角色拦截
        filterMap.put("/sys/admin", "authc,roles[admin]");
        filterMap.put("/sys/user", "authc,roles[user]");
        filterMap.put("/sys/company", "authc,roles[company]");
        //权限拦截  设置admin下的所有方法都需要增删改查权限
        filterMap.put("/sys/admin/*", "perms[admin:add,admin:update,admin:delete,admin:find]");
        //设置user下的add，update，delete需要特定权限
//        filterMap.put("/sys/user/find", "perms[user:find]");
//        filterMap.put("/sys/user/delete", "perms[user:delete]");
//        filterMap.put("/sys/user/add", "perms[user:add]");
//        filterMap.put("/sys/user/update", "perms[user:update]");
        //设置登出
        filterMap.put("/logout", "logout");
        //设置admin下的某个方法需要某个权限
        // filterMap.put("/sys/admin/find", "perms[admin:find]");

        // 添加自己的过滤器并且取名为jwt
        Map<String, Filter> filter = new HashMap<String, Filter>(1);
        filter.put("jwt", new AuthFilter());
        shiroFilterFactoryBean.setFilters(filter);
        // <!-- 过滤链定义，从上向下顺序执行，一般将/**放在最为下边
        filterMap.put("/**", "jwt");
        //设置登录请求
        shiroFilterFactoryBean.setLoginUrl("/login");
        //设置401（无权限界面）
        shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }
    //DefaultWebSecurityManager:2
    @Bean("DefaultWebSecurityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("AuthorizingRealm") AuthorizingRealm myRealm) {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        //关联userRealm
        defaultWebSecurityManager.setRealm(myRealm);
        return defaultWebSecurityManager;
    }
    //创建 realm对象,需要自定义:1
    @Bean("AuthorizingRealm")
    public AuthorizingRealm getMyRealm() {
        MyRealm myRealm = new MyRealm();
        // 因为使用了token,所以这里不需要再设置加密
//        myRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myRealm;
    }

    /**
     * description: 密码加密算法设置
     * date: 2021年-04月-16日 13:58
     * author: zhanghang
     * 
     * @param 
     * @return org.apache.shiro.authc.credential.HashedCredentialsMatcher
     */ 
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName(Md5Hash.ALGORITHM_NAME);
        // 散列次数
        hashedCredentialsMatcher.setHashIterations(2);
        return hashedCredentialsMatcher;
    }
    /**
     * 配置shiro和thymeleaf整合
     *
     * @return
     */
    @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }

    /**
     * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可实现此功能
     */ 
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        autoProxyCreator.setProxyTargetClass(true);
        return autoProxyCreator;
    }

    /**
     * 开启aop注解支持
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("DefaultWebSecurityManager")DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

}
